#ifndef SOS_REGION_H
#define SOS_REGION_H

/**
 *  Virtual memory regions for SOS processes.
 *  Regions are lazily mapped. Most ops happen in O(1) or O(num_regions).
 *  This enables a mostly-synchronous VM subsystem, with all annoying async ops
 *  happening within the fault handler.
 */

#include "include.h"

#define SOS_REGION_SUCCESS (0)
#define SOS_REGION_INVAL   (1)
#define SOS_REGION_OOM     (2)

typedef struct page_attrs page_attrs;

/* An individual region is just an element in a sorted DLL */
typedef struct sos_region {
    seL4_Word base;   /* Base address. Must be page-aligned. */
    seL4_Word npages; /* Number of pages in the region. */
    page_attrs attrs; /* Attributes of all pages in the region. */

    /* Region list is managed as a doubly-linked list by libut */
    struct sos_region *next;
    struct sos_region *prev;
} sos_region;

/* List operations may update the head pointer */
typedef sos_region **sos_region_list;

/** Add a npages-length region starting at base to the region list list.
 *  @return SOS_REGION_INVAL on illegal range (e.g. overlap),
 *  else SOS_REGION_SUCCESS.
 */
int sos_add_region(sos_region_list list, seL4_Word base, seL4_Word npages,
                   page_attrs attrs);

/** Grow or shrink a given region. Resizing to 0 deletes the region.
 *  @return SOS_REGION_INVAL on illegal range (e.g. overlap), else
 *          SOS_REGION_SUCCESS.
 */
int sos_resize_region(sos_region_list list, sos_region *region,
                      seL4_Word new_npages);

/** Equivalent to resizing a region to 0. */
int sos_remove_region(sos_region_list list, sos_region *region);

/** Given a process virtual address, walk the region list and find the
 *  relevant region.
 *  @param region Pointer to memory that will store address of resolved region.
 *  @return SOS_REGION_INVAL if address does not fall within any regions,
 *          else SOS_REGION_SUCCESS.
 */
int sos_resolve_region(sos_region_list list, seL4_Word proc_vaddr,
                       sos_region **region);

/**
 * Pretty-print a given region.
 */
void sos_print_region(sos_region *region);

#endif // SOS_REGION_H
